using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;

// 原生API定义（与之前的FileDialogNative保持一致）
internal static class FileDialogNative
{
    [Flags]
    public enum FOS : uint
    {
        FOS_ALLOWMULTISELECT = 0x200,
        FOS_PICKFOLDERS = 0x20,
        FOS_FORCEFILESYSTEM = 0x40,
    }

    [ComImport]
    [Guid("42f85136-db7e-439c-85f1-e4075d135fc8")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IFileDialog
    {
        [PreserveSig]
        int Show(IntPtr parent);
        void SetOptions(FOS fos);
        void GetResult(out IntPtr ppsi);
        void SetTitle([MarshalAs(UnmanagedType.LPWStr)] string pszTitle);
        // 其他接口方法省略（保持与原生API一致）
    }

    [ComImport]
    [Guid("b63ea76d-1f85-456f-a19c-48159efa858b")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IShellItem
    {
        void GetDisplayName(uint sigdnName, out IntPtr ppszName);
        // 其他接口方法省略
    }

    [ComImport]
    [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IShellItemArray
    {
        void GetCount(out uint cItems);
        void GetItemAt(uint index, out IShellItem ppsi);
        // 其他接口方法省略
    }

    [ComImport]
    [Guid("dc1c5a9c-e88a-4dde-a5a1-60f82a20aef7")]
    public class FileOpenDialogRCW { }

    public const uint SIGDN_FILESYSPATH = 0x80058000; // 文件系统路径标识
}

public class NativeFileDialog
{
    public string Title { get; set; }
    public bool AllowMultiSelect { get; set; }
    public bool AllowFolders { get; set; }

    public string[] ShowDialog(IWin32Window owner = null)
    {
        var selectedPaths = new List<string>();
        IntPtr parentHandle = owner?.Handle ?? IntPtr.Zero;

        try
        {
            // 1. 创建原生文件对话框实例
            FileDialogNative.IFileDialog dialog = new FileDialogNative.FileOpenDialogRCW() as FileDialogNative.IFileDialog;
            if (dialog == null)
                return selectedPaths.ToArray();

            // 2. 配置对话框选项
            FileDialogNative.FOS options = FileDialogNative.FOS.FOS_FORCEFILESYSTEM;
            if (AllowMultiSelect)
                options |= FileDialogNative.FOS.FOS_ALLOWMULTISELECT;
            if (AllowFolders)
                options |= FileDialogNative.FOS.FOS_PICKFOLDERS;
            dialog.SetOptions(options);

            // 3. 设置对话框标题
            if (!string.IsNullOrEmpty(Title))
                dialog.SetTitle(Title);

            // 4. 显示对话框并检查结果
            int dialogResult = dialog.Show(parentHandle);
            if (dialogResult != 0) // 0 表示用户点击了"确定"
                return selectedPaths.ToArray();

            // 5. 获取选择结果（关键步骤）
            dialog.GetResult(out IntPtr shellItemPtr);
            if (shellItemPtr == IntPtr.Zero)
                return selectedPaths.ToArray();

            // 6. 处理单选/多选结果
            if (AllowMultiSelect)
            {
                // 多选时，结果是IShellItemArray接口
                var shellItemArray = Marshal.GetObjectForIUnknown(shellItemPtr) as FileDialogNative.IShellItemArray;
                if (shellItemArray != null)
                {
                    shellItemArray.GetCount(out uint count);
                    for (uint i = 0; i < count; i++)
                    {
                        shellItemArray.GetItemAt(i, out var shellItem);
                        if (shellItem != null)
                        {
                            string path = GetPathFromShellItem(shellItem);
                            if (!string.IsNullOrEmpty(path))
                                selectedPaths.Add(path);
                            Marshal.ReleaseComObject(shellItem);
                        }
                    }
                    Marshal.ReleaseComObject(shellItemArray);
                }
            }
            else
            {
                // 单选时，结果是单个IShellItem
                var shellItem = Marshal.GetObjectForIUnknown(shellItemPtr) as FileDialogNative.IShellItem;
                if (shellItem != null)
                {
                    string path = GetPathFromShellItem(shellItem);
                    if (!string.IsNullOrEmpty(path))
                        selectedPaths.Add(path);
                    Marshal.ReleaseComObject(shellItem);
                }
            }

            Marshal.Release(shellItemPtr); // 释放非托管资源
        }
        catch (Exception ex)
        {
            MessageBox.Show($"获取路径失败: {ex.Message}", "错误");
        }

        return selectedPaths.ToArray();
    }

    // 从IShellItem提取文件系统路径
    private string GetPathFromShellItem(FileDialogNative.IShellItem shellItem)
    {
        try
        {
            // 调用GetDisplayName获取路径，使用SIGDN_FILESYSPATH标识
            shellItem.GetDisplayName(FileDialogNative.SIGDN_FILESYSPATH, out IntPtr pathPtr);
            if (pathPtr != IntPtr.Zero)
            {
                string path = Marshal.PtrToStringAuto(pathPtr); // 转换为C#字符串
                Marshal.FreeCoTaskMem(pathPtr); // 释放非托管字符串内存
                return path;
            }
        }
        catch { /* 忽略无权限或无效路径的错误 */ }
        return null;
    }
}

// 使用示例
public class UsageExample
{
    public void Demonstrate()
    {
        var dialog = new NativeFileDialog
        {
            Title = "选择文件或目录（可多选）",
            AllowMultiSelect = true,
            AllowFolders = true // 允许同时选择文件和目录
        };

        string[] selectedPaths = dialog.ShowDialog();
        if (selectedPaths != null && selectedPaths.Length > 0)
        {
            MessageBox.Show($"选中了 {selectedPaths.Length} 项:\n\n{string.Join("\n", selectedPaths)}", "选择结果");
        }
    }
}
